package mornd.test2;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;
import java.util.Map;

/**
 * @author: mornd
 * @dateTime: 2023/5/4 - 15:18
 */
public class TestBeanFactory {
    /**
     * 结论：
     * beanFactory
     * 不会主动调用 BeanFactoryPostProcessor 和 BeanPostProcessor 处理器
     * 不会主动初始化单例对象
     * 不会解析 ${} 和 #{}
     *
     * @param args
     */
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // 生成 beanDefinition 对象
        AbstractBeanDefinition beanDefinition =
                BeanDefinitionBuilder.genericBeanDefinition(Config.class)
                .setScope("singleton")
                .getBeanDefinition();

        // 注册进容器中
        beanFactory.registerBeanDefinition("config", beanDefinition);

        System.out.println(Arrays.toString(beanFactory.getBeanDefinitionNames())); // [config]

        // 给 beanFactory 添加一些常用的后置处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
            /*
config
org.springframework.context.annotation.internalConfigurationAnnotationProcessor 解析 @Configuration
org.springframework.context.annotation.internalAutowiredAnnotationProcessor 解析 @Autowired
org.springframework.context.annotation.internalCommonAnnotationProcessor 解析 @Resource
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
             */
        }

        // 获取所有的 BeanFactory 后置处理器（后置处理器都实现 BeanFactoryPostProcessor）
        // 后置处理器的主要功能，补充了一些 bean 定义，例如解析 @Configuration 等注解
        Map<String, BeanFactoryPostProcessor> beansOfType =
                beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);

        beansOfType.values().forEach(v -> {
            v.postProcessBeanFactory(beanFactory);
        });

        System.out.println("------------------");
        String[] beanDefinitionNames2 = beanFactory.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames2) {
            System.out.println(beanDefinitionName);
            /*
            config
            org.springframework.context.annotation.internalConfigurationAnnotationProcessor
            org.springframework.context.annotation.internalAutowiredAnnotationProcessor
            org.springframework.context.annotation.internalCommonAnnotationProcessor
            org.springframework.context.event.internalEventListenerProcessor
            org.springframework.context.event.internalEventListenerFactory
            bean1
            bean2
             */
        }
        //System.out.println(beanFactory.getBean(Bean1.class).getBean2());

        // bean 的后置处理器，针对 bean 的生命周期的各个阶段提供扩展 @Autowired @Resource
        beanFactory.addBeanPostProcessors(
                beanFactory.getBeansOfType(BeanPostProcessor.class).values()
        );

        //beanFactory.preInstantiateSingletons();// 预先创建好所有单例对象
        System.out.println("-------------->"); // bean1，bean2构造器是在这一步之后打印
// 如果在这一步之前已经获取过 Bean1 会使bean1提前创建，那么@Autowired 注解就失效了，这里的输出还是 null
        System.out.println(beanFactory.getBean(Bean1.class).getBean2());
    }

    @Configuration
    static class Config {

        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2() {
            return new Bean2();
        }
    }

    static class Bean1{
        @Autowired
        private Bean2 bean2;

        public Bean1() {
            System.out.println("bean1 构造器");
        }

        public Bean2 getBean2() {
            return bean2;
        }
    }

    static class Bean2{
        public Bean2() {
            System.out.println("bean2 构造器");
        }
    }
}
